WebApplicationContext 中特殊的 bean 类型(二)--- LocaleResolver

本章承接前面的内容,继续讲述 LocaleResolver。

LocalResolver 的作用是解析客户的请求来自什么地区,这样就可以针对请求中的地区信息,返回不同语言的视图,以满足 Spring MVC 工程国际化的需要。而 LocalContextResolver 则继承自 LocalResolver 接口,加入了对时区的支持。

LocalResolver 源码

首先来看 LocalResolver 的默认配置(AcceptHeaderLocaleResolver)的源码,该配置实现了 LocalResolver 的接口,并且重写 resolveLocale 方法,使其可以通过 Request 的 Header 字段解析请求的地区信息:

1
2
3
4
5
6
7
8
9
10
11
12
public class AcceptHeaderLocaleResolver implements LocaleResolver {
public AcceptHeaderLocaleResolver() {
}

public Locale resolveLocale(HttpServletRequest request) {
return request.getLocale();
}

public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
throw new UnsupportedOperationException("Cannot change HTTP accept header - use a different locale resolution strategy");
}
}

可以看到,这里 resolveLocale 方法直接去拿了请求中的 locale 字段,查看客户端这边最支持哪种语言。并且该类不支持 set 方法。

LocalResolver 代码实例

locale 专属的 properties 文件

首先,我们需要配置三个对应语言的 resource 文件,在 resources/locales 文件夹下分别创建 locale_en.properties, locale_en_US.properties, locale_zh_CN.properties 文件,注意直接创建这三个文件后 Intellij 会把它合到一个文件夹里面(这里应该会变成一个名为 locale 文件夹)。properties 文件内的代码分别是:

1
2
# locale_en.properties 文件
message.locale=en_hello
1
2
# locale_en_US.properties 文件
message.locale=en_US_hello
1
2
# locale_zh_CN.properties 文件
message.locale=zh_CN_hello

LocaleResolver 在 Spring 配置文件中的配置

在 root-context 配置 LocalResolver 的 bean,并且配置对应的国际化资源文件 ReloadableResourceBundleMessageSource,其中的方法可以针对输入的 Locale 对象去获取对应的 resource 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8"?>
<beans>

<context:component-scan base-package="com.test.myapp.example"/>

<!-- 其余 bean 配置 -->

<!--LocaleResolver 配置-->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver">
</bean>

<!-- 国际化资源文件 -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<!-- 如果资源文件放在classpath下,basename的value必须有classpath:前缀,否则报错:No message found under code... -->
<!-- 这个地方 value 是红色也没问题,Spring MVC 在运行的时候还是会找到这些资源文件 -->
<property name="basename" value="classpath:locales/locale" />
<!-- 如果在国际化资源文件中找不到对应代码的信息,就用这个代码作为名称返回 -->
<!--<property name="useCodeAsDefaultMessage" value="true" />-->
<!--<property name="defaultEncoding" value="ISO-8859-1"/>-->
</bean>

<!-- 其余 bean 配置 -->

</beans>

LocaleResolver 测试接口

然后就是为我们的 LocaleResolver 配置一个接口,该接口的功能是获取发出当前的客户端支持哪些语言,并且最为偏好的语言是什么,之后再去获取对应的 properties 文件中的信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Controller
public class LocaleResolverController {
@RequestMapping(value="/accept-header-resolver.do", method = RequestMethod.GET)
public ModelAndView resolveLocale(HttpServletRequest request) {
String clientLocale = "";
// 获取客户端支持的语言
Enumeration<Locale> locales = request.getLocales();
while (locales.hasMoreElements()) {
Locale locale = locales.nextElement();
clientLocale += locale + ",";
}
RequestContext requestContext = new RequestContext(request);
// 获取对应地区的 properties 中的信息
String value = requestContext.getMessage("message.locale");

ModelAndView modelAndView = new ModelAndView("localeResolver");

modelAndView.addObject("clientLocale", clientLocale);
modelAndView.addObject("currentLocale", requestContext.getLocale());
modelAndView.addObject("localeResource", value);
return modelAndView;
}
}

上述代码中 clientLocale 表示客户端浏览器支持的语言,currentLocale 则是客户端的偏好语言,value 则表示根据客户端偏好语言取回的对应语言 properties 中的字段值。

LocaleResolver 测试前端页面

上面测试接口返回的是一个 ModelAndView 对象,因此,我们还需要 jsp 前端文件,来输出上述的字段:

1
2
3
4
5
6
7
8
9
10
11
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>locale resolver page</title>
</head>
<body>
<p>
客户端支持:${clientLocale} 客户端当前地区:${currentLocale}, 服务端对应内容:${localeResource}
</p>
</body>
</html>

我们已经完成了具体代码的编写,下面进入测试。

测试

这次测试以 chrome 为例,首先查看 chrome 设置部分:

chrome 语言设置

可以看到,语言设置这一栏我们把偏好语言设为英语(EN)。运行工程后,在浏览器中输入:http://localhost:8080/accept-header-resolver.do,我们会看到如下的标识:

1
客户端支持:en,zh,en_US,zh_CN, 客户端当前地区:en, 服务端对应内容:en_hello

之后,我们在语言设置中把中文(简体)(zh_CN)放在语言偏好的第一位,再输入相同的地址,则会出现如下的标识:

1
客户端支持:zh_CN,zh,en,en_US, 客户端当前地区:zh_CN, 服务端对应内容:zh_CN_hello

这可以说明,我们的 LocaleResolver 在工程已经生效。